/*
 * There are six different styles of attributes in the
 * 2.0 DTD.  The DTDAttribute structure has been designed
 * to hold inforamation from any type.  We use flags to
 * show which fields are valid.  Note that name and type
 * are always valid.  Below are examples of the attributes
 * found in the HTML 2.0 DTD.
 *
 * In markup H1:
 *	SDAFORM  CDATA  #FIXED "H1"
 *	Type is A_FIXED, datatype is CDATA, default string is "H1"
 *
 * In markup IMG:
 *	SRC CDATA #REQUIRED
 *	Type is A_REQUIRED, datatype is CDATA
 *
 * In markup A:
 *	HREF CDATA #IMPLIED
 *	Type is A_IMPLIED, datatype is CDATA
 *
 * In markup FORM:
 *	METHOD ( GET | POST ) GET
 *	Type is A_IMPLIED, list contains GET, POST, default atom is GET
 *
 * In markup FORM:
 *	ENCTYPE CDATA "application/x-www-form-urlencoded"
 *	Type is A_IMPLIED, datatype is CDATA, default string is "applicati...
 *
 * In markup IMG:
 *	ALIGN (top|middle|bottom) #IMPLIED
 *	Type is A_IMPLIED, list contains top, middle, bottom
 *
 * Other possibilities may show up in future DTDs, so beware.
 */

#ifndef DTD_H
#define DTD_H

#define A_REQUIRED	1
#define A_FIXED		2
#define A_IMPLIED	3

#define AF_DATATYPE	0x1
#define AF_LIST		0x2
#define AF_DEFSTRING	0x4
#define AF_DEFATOM	0x8

typedef struct dtd_attribute {
    atom name;
    int type;
    unsigned int valid;
    atom dataType;
    atom list[10];
    char *defString;
    atom defAtom;
} DTDAttribute;

/*
 * There are three cases for an element's terminator:
 *   It can be required (TERM_MAND)
 *   It can be non-existant (TERM_NONE)
 *   It can be optional (TERM_OPT)
 * Some elements can be implied (ie. HEAD or HTML) (ELE_OPT)
 */
#define E_TERM_MAND	0x001
#define E_TERM_NONE	0x002
#define E_TERM_OPT	0x004
#define E_ELE_OPT	0x008

typedef struct dtd_element {
    atom name;
    int flags;
    atom children[40];		/* Allowed children */
    atom parents[40];		/* Allowed parents */
    DTDAttribute attrs[10];	/* Attribute details (info) list */
    atom attrList[10];		/* Attribute atom list */
    atom reqAttrs[10];		/* Required Attributes */
    atom fixedAttrs[10];	/* Fixed Attributes */
    atom impliedAttrs[10];	/* Implied Attributes */
} DTDElement;

void InitDTD();
atom *GetElementChildren(atom element);
atom *GetElementParents(atom element);
atom *GetElementAttrList(atom element);
DTDAttribute *GetElementAttrInfo(atom element, atom attr);
DTDElement *ChangeElementInfo(atom element, DTDElement *new);
int AddElementParent(atom element, atom child);
int AddElementChild(atom element, atom child);
DTDElement *GetElementInfo(atom element);
atom *GetElementReqAttrs(atom element);
atom *GetElementFixedAttrs(atom element);
atom *GetElementImpliedAttrs(atom element);
int GetElementTerminator(atom element);
int ValidRelationship(atom parent, atom child);

#define IsEleOptTermed(element) \
			(GetElementTerminator(element) == E_TERM_OPT)

#define IsEleMandTermed(element) \
			(GetElementTerminator(element) == E_TERM_MAND)

#define IsEleNoneTermed(element) \
			(GetElementTerminator(element) == E_TERM_NONE)

#define IsElementImplied(element) \
			(GetElementTerminator(element) == E_ELE_OPT)

#define ValidAttribute(element, attr) (GetElementAttrInfo((element), (attr)))

#endif
